package com.edu.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.edu.mapper.ExaminationInfoMapper;
import com.edu.mapper.ExaminationMapper;
import com.edu.pojo.*;
import com.edu.service.ExaminationService;
import com.edu.util.JsonUtil;
import com.edu.util.RedisClientUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author five-five
 * @created 2021/11/12 - 15:32
 */
@Service
public class ExaminationServiceImpl implements ExaminationService {
    @Resource
    private ExaminationMapper examinationMapper;
    @Resource
    private ExaminationInfoMapper examinationInfoMapper;
    @Resource
    private RedisClientUtil redisClientUtil;

    /**
     * @param length  >0
     * @param name
     * @param request
     * @return
     */
    @Override
    public RestResult randomGenerateExamination(int length, String name, HttpServletRequest request) {
        User user = null;
        try {
            user = (User) request.getSession().getAttribute("user");
        } catch (Exception e) {
            e.printStackTrace();
        }
        //判断试卷名是否重复
        List<Examination> examinations = getExaminationByNameAndUserId(name, user);
        if (CollectionUtil.isNotEmpty(examinations)) {
            return RestResult.build(StateEnum.ERROR_ENTITY.getCode(), "该用户已存在" + name + "试卷名，请重新输入");
        }
        //---
        List<Excise> exciseList = randomSelectExcises(length);
        Examination examination = new Examination();
        if (user == null || StringUtils.isBlank(user.getId() + "")) {
            user = new User();
            user.setId(1);
        }
        examination.setCreateUser(user.getId());
        examination.setName(name);
        //插入试卷信息
        examinationMapper.insertSelective(examination);
        int examinationId = examination.getId();
        //插入试卷详情信息
        ExaminationInfo examinationInfo = new ExaminationInfo();
        examinationInfo.setExaminationId(examinationId);
        examinationInfo.setStatus(0);
        examinationInfo.setUserId(user.getId());
        for (Excise excise : exciseList) {
            examinationInfo.setRedisKey(excise.getRedisKey());
            examinationInfoMapper.insertSelective(examinationInfo);
        }
        return RestResult.build(StateEnum.SUCCESS.getCode(), StateEnum.SUCCESS.getText(), examination);
    }

    /**
     * 根据用户id查询他所有的Examination
     *
     * @param userId 用户id
     * @return RestResult
     */
    @Override
    public RestResult getExaminationByUserId(int userId) {
        List<Examination> examinations = null;
        try {
            examinations = examinationMapper.getExaminationByUserId(userId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return RestResult.ok(examinations);
    }

    @Override
    public RestResult chooseAndDoIt(Examination examination, int kind) {
        List<Excise> exciseList = new ArrayList<>();
        ExaminationInfoExample examinationInfoExample = new ExaminationInfoExample();
        ExaminationInfoExample.Criteria criteria = examinationInfoExample.createCriteria();
        criteria.andExaminationIdEqualTo(examination.getId());
        List<ExaminationInfo> examinationInfos = examinationInfoMapper.selectByExample(examinationInfoExample);
        examinationInfos = filterBykind(examinationInfos, kind);
        examinationInfos.forEach(examinationInfo -> {
            String redisKey = examinationInfo.getRedisKey();
            Excise excise = JsonUtil.jsonToPojo(redisClientUtil.get(redisKey), Excise.class);
            excise.setRedisKey(redisKey);
            exciseList.add(excise);
        });
        return RestResult.ok(exciseList);
    }

    /**
     * 根据kind的值进行过滤
     *
     * @param examinationInfos
     * @param kind             0全部，1错误，2正确
     * @return
     */
    private List<ExaminationInfo> filterBykind(List<ExaminationInfo> examinationInfos, int kind) {
        if (kind == 1) {
            //错误
            examinationInfos = examinationInfos.stream().filter(examinationInfo -> examinationInfo.getStatus() == 2).collect(Collectors.toList());
        }
        if (kind == 2) {
            //正确
            examinationInfos = examinationInfos.stream().filter(examinationInfo -> examinationInfo.getStatus() == 3).collect(Collectors.toList());
        }
        return examinationInfos;
    }

    @Override
    public RestResult modifyExamination(String examinationStr, HttpServletRequest request) {
        Examination examination = (Examination) request.getSession().getAttribute("examination");
        List<Excise> exciseList = JsonUtil.jsonToList(examinationStr, Excise.class);
        //完善返回的数据
        ExaminationVo examinationVo = new ExaminationVo();
        //设置当前考试试卷ID
        examinationVo.setCurrentExaminationId(examination.getId());
        //总题数
        examinationVo.setTotalProblems(exciseList.size());
        for (Excise excise : exciseList) {
            int left = Integer.parseInt(excise.getLeft());
            int right = Integer.parseInt(excise.getRight());
            int result = Integer.parseInt(excise.getResult());;
            int calculation = excise.getSymbol().equals("+") ? left + right : left - right;
            //你碰了试卷我就算是你做了
            int state = 1;
            if (calculation == result) {
                state = 3;
                examinationVo.setRightProblems(examinationVo.getRightProblems() + 1);
            } else {
                state = 2;
                examinationVo.setErrorProblems(examinationVo.getErrorProblems() + 1);
            }
            ExaminationInfo examinationInfo = new ExaminationInfo();
            examinationInfo.setRedisKey(excise.getRedisKey());
            examinationInfo.setExaminationId(examination.getId());
            examinationInfo.setUserId(examination.getCreateUser());
            examinationInfo.setStatus(state);
            examinationInfoMapper.updateStateByUserAndRedisKeyAndExaminationId(examinationInfo);
        }
        //正确率
        examinationVo.setRightRate((((double) examinationVo.getRightProblems() / (double) examinationVo.getTotalProblems())));
        //错误率
        examinationVo.setErrorRate(1d - examinationVo.getRightRate());
        return RestResult.ok(examinationVo);
    }

    @Override
    public RestResult getFinishedExamination(String userId) {
        //todo：查询用户做过的试卷
        List<Examination> examinationList = examinationInfoMapper.getFinishedExaminationByUserId(userId);
        //todo：生成Examination对象对应的ExaminationVo(统计情况对象)
        for (Examination examination : examinationList) {
            //bug：Mybatis映射不过来这个属性。。。。真的蠢
            examination.setCreateUser(Integer.parseInt(userId));
            ExaminationVo examinationVo = fullExaminationVoByExamination(examination);
            examination.setExaminationVo(examinationVo);
        }
        return RestResult.ok(examinationList);
    }

    /**
     * 通过examination填充ExaminationVo填充对象
     *
     * @param examination 查询对象
     * @return
     */
    private ExaminationVo fullExaminationVoByExamination(Examination examination) {
        ExaminationVo examinationVo = new ExaminationVo();
//        ExaminationInfoExample examinationInfoExample = new ExaminationInfoExample();
//        ExaminationInfoExample.Criteria criteria = examinationInfoExample.createCriteria();
//        criteria.andExaminationIdEqualTo(examination.getId());
//        criteria.andUserIdEqualTo(examination.getCreateUser());
        List<ExaminationInfo> examinationInfos = examinationInfoMapper.selectByExamination(examination);
        long rightProblems = examinationInfos.stream().filter(examinationInfo -> examinationInfo.getStatus() == 3).count();
        long errorProblems = examinationInfos.stream().filter(examinationInfo -> examinationInfo.getStatus() == 2).count();
        examinationVo.setRightProblems((int) rightProblems);
        examinationVo.setErrorProblems((int) errorProblems);
        examinationVo.setCurrentExaminationId(examination.getId());
        examinationVo.setTotalProblems(examinationInfos.size());
        examinationVo.setRightRate((double) rightProblems / (double) examinationInfos.size());
        examinationVo.setErrorRate(1.00d - examinationVo.getRightRate());
        return examinationVo;
    }

    private List<Examination> getExaminationByNameAndUserId(String name, User user) {
        Examination examination = new Examination();
        examination.setCreateUser(user.getId());
        examination.setName(name);
        List<Examination> examinations = examinationMapper.selectByNameAndUserId(examination);
        return examinations;
    }

    /**
     * 直接从redis中随机选取length个题目
     *
     * @param length
     * @return
     */
    private List<Excise> randomSelectExcises(int length) {
        List<Excise> exciseList = new ArrayList<>();
        HashSet<Integer> hashSet = new HashSet<>();
        int addmaxlength = Integer.parseInt(redisClientUtil.get(AllKeyEnum.ADD_MAX_LENGTH.getKey()));
        int subtractmaxlength = Integer.parseInt(redisClientUtil.get(AllKeyEnum.SUBTRACT_MAX_LENGTH.getKey()));
        int mid = length / 2;
        while (exciseList.size() < mid) {
            String key = AllKeyEnum.PREFIX_ADD_EXCISES.getKey() + ((int) (Math.ceil(Math.random() * addmaxlength)) - 1);
            String s = redisClientUtil.get(key);
            Excise e = JsonUtil.jsonToPojo(s, Excise.class);
            e.setRedisKey(key);
            exciseList.add(e);
        }
        while (exciseList.size() < length) {
            String key = AllKeyEnum.PREFIX_SUBTRACT_EXCISES.getKey() + ((int) (Math.ceil(Math.random() * subtractmaxlength)) - 1);
            String s = redisClientUtil.get(key);
            Excise e = JsonUtil.jsonToPojo(s, Excise.class);
            e.setRedisKey(key);
            exciseList.add(e);
        }
        return exciseList;
    }
}
